package com.zwf.infrastructure.persistent.repository;

import com.zwf.domain.strategy.model.entity.StrategyAwardEntity;
import com.zwf.domain.strategy.model.entity.StrategyEntity;
import com.zwf.domain.strategy.model.entity.StrategyRuleEntry;
import com.zwf.domain.strategy.repository.IStrategyRepository;
import com.zwf.infrastructure.persistent.dao.*;
import com.zwf.infrastructure.persistent.po.PointConsume;
import com.zwf.infrastructure.persistent.po.StrategyAward;
import com.zwf.infrastructure.persistent.po.StrategyRule;
import com.zwf.infrastructure.persistent.po.UserBlacklist;
import com.zwf.infrastructure.persistent.redis.IRedisService;
import com.zwf.types.common.Constants;
import com.zwf.types.enums.ResponseCode;
import com.zwf.types.exception.AppException;
import org.redisson.api.RMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * @Author zwf
 * @description 策略仓储实现
 * @date 2024/7/1 12:07
 */
@Repository
public class StrategyRepository implements IStrategyRepository {

    @Autowired
    private IStrategyAwardDAO strategyAwardDAO;

    @Autowired
    private IStrategyDAO strategyDAO;

    @Autowired
    private IStrategyRuleDAO strategyRuleDAO;

    @Autowired
    private IRedisService redisService;

    @Autowired
    private IUserBlacklistDAO userBlacklistDAO;

    @Autowired
    private IPointConsumeDAO pointConsumeDAO;

    @Override
    public List<StrategyAwardEntity> queryStrategyAwardList(Long strategyId) {
        String cacheKey = Constants.RedisKey.STRATEGY_AWARD_KEY + strategyId;
        List<StrategyAwardEntity> strategyAwardEntities = redisService.getValue(cacheKey);
        if(strategyAwardEntities != null && !strategyAwardEntities.isEmpty()){
            return strategyAwardEntities;
        }
        List<StrategyAward> strategyAwards = strategyAwardDAO.queryStrategyAwardListByStrategyId(strategyId);
        strategyAwardEntities = new ArrayList<>(strategyAwards.size());
        for(StrategyAward strategyAward : strategyAwards){
            StrategyAwardEntity strategyAwardEntity = StrategyAwardEntity.builder()
                    .strategyId(strategyAward.getStrategyId())
                    .awardId(strategyAward.getAwardId())
                    .awardCount(strategyAward.getAwardCount())
                    .awardCountSurplus(strategyAward.getAwardCountSurplus())
                    .awardRate(strategyAward.getAwardRate())
                    .build();
            strategyAwardEntities.add(strategyAwardEntity);
        }
        redisService.setValue(cacheKey,strategyAwardEntities);
        return strategyAwardEntities;
    }

    @Override
    public void storeStrategyAwardSearchRateTablesToRedis(String key, Integer rateRange, HashMap<Integer, Integer> shuffleStrategyAwardSearchRateTables) {
        //存储抽奖策略概率值，如10000，用于生成10000以内的随机数
        redisService.setValue(Constants.RedisKey.STRATEGY_RATE_RANGE_KEY + key, Integer.valueOf(rateRange.intValue()));
        //存储概率查找表
        RMap<Integer, Integer> cacheRateTable = redisService.getMap(Constants.RedisKey.STRATEGY_RATE_TABLE_KEY + key);
        cacheRateTable.putAll(shuffleStrategyAwardSearchRateTables);
    }

    @Override
    public Integer getRateRange(Long strategyId) {
        Integer rateRange = redisService.getValue(Constants.RedisKey.STRATEGY_RATE_RANGE_KEY + strategyId);
        if(rateRange!=null){
            return rateRange;
        }else {
            throw new AppException(ResponseCode.RATE_RANGE_IS_NOLL.getCode(),ResponseCode.RATE_RANGE_IS_NOLL.getInfo());
        }
    }

    @Override
    public Integer getRateRange(String key) {
        Integer rateRange = redisService.getValue(Constants.RedisKey.STRATEGY_RATE_RANGE_KEY + key);
        if(rateRange!=null){
            return rateRange;
        }else {
            throw new AppException(ResponseCode.RATE_RANGE_IS_NOLL.getCode(),ResponseCode.RATE_RANGE_IS_NOLL.getInfo());
        }
    }

    @Override
    public Integer getStrategyAwardAssemble(String key, int rateKey) {
        Integer awardId = redisService.getFromMap(Constants.RedisKey.STRATEGY_RATE_TABLE_KEY + key, rateKey);
        if(awardId != null){
            return awardId;
        }else {
            throw new AppException(ResponseCode.AWARD_ID_IS_NOLL.getCode(),ResponseCode.AWARD_ID_IS_NOLL.getInfo());
        }
    }

    @Override
    public StrategyEntity queryStategyEntity(Long strategyId) {
        StrategyEntity strategyEntity = redisService.getValue(Constants.RedisKey.STRATEGY_ENTITY_KEY + strategyId);
        if(strategyEntity != null){
            return strategyEntity;
        }
        strategyEntity = strategyDAO.queryStrategyEntityByStrategyId(strategyId);
        redisService.setValue(Constants.RedisKey.STRATEGY_ENTITY_KEY + strategyId, strategyEntity);
        return strategyEntity;
    }

    @Override
    public StrategyRuleEntry queryStrategyRuleEntity(Long strategyId, String ruleModel) {
        // StrategyRuleEntry strategyRuleEntry = redisService.getValue(Constants.RedisKey.STRATEGY_RULE_ENTITY_KEY + strategyId);
        // if(strategyRuleEntry != null){
        //     return strategyRuleEntry;
        // }
        StrategyRule strategyRule = new StrategyRule();
        strategyRule.setStrategyId(strategyId);
        strategyRule.setRuleModel(ruleModel);
        StrategyRuleEntry strategyRuleEntry = strategyRuleDAO.queryStrategyRule(strategyRule);
        // redisService.setValue(Constants.RedisKey.STRATEGY_RULE_ENTITY_KEY + strategyId, strategyRuleEntry);
        return strategyRuleEntry;
    }

    @Override
    public String queryStrategyRuleValue(Long strategyId, Integer awardId, String ruleModel) {
        StrategyRule strategyRule = new StrategyRule();
        strategyRule.setStrategyId(strategyId);
        strategyRule.setAwardId(awardId);
        strategyRule.setRuleModel(ruleModel);
        String ruleValue = strategyRuleDAO.queryStrategyRuleValue(strategyRule);
        return ruleValue;
    }

    @Override
    public Integer queryUserBlacklist(Long userId, Long strategyId) {
        UserBlacklist userBlacklist = new UserBlacklist();
        userBlacklist.setUserId(userId);
        userBlacklist.setStrategyId(strategyId);
        Integer isBlacklist = userBlacklistDAO.isExist(userBlacklist);
        return isBlacklist;
    }

    @Override
    public Integer queryPointAccumulate(Long userId, Long strategyId) {
        PointConsume pointConsume = new PointConsume();
        pointConsume.setUserId(userId);
        pointConsume.setStrategyId(strategyId);
        Integer accumulate = pointConsumeDAO.queryPointAccumulate(pointConsume);
        return accumulate;
    }

    @Override
    public StrategyEntity queryStrategyEntity(Long strategyId) {
        StrategyEntity strategyEntity = strategyDAO.queryStrategyEntityByStrategyId(strategyId);
        return strategyEntity;
    }
}
